const PROMISE_STATUS_PENDING = "pending";
const PROMISE_STATUS_FULFILLED = "fulfilled";
const PROMISE_STATUS_REJECTED = "rejected";

const execFunctionWithCatchError = (excuFn, value, resolve, reject) => {
  try {
    const result = excuFn(value);
    resolve(result);
  } catch (error) {
    reject(error);
  }
};

class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.fulfilledFns = [];
    this.rejectedFns = [];
    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return;
          this.status = PROMISE_STATUS_FULFILLED;
          this.value = value;
          this.fulfilledFns.forEach((fn) => {
            fn();
          });
        });
      }
    };

    const reject = (reason) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return;
          this.status = PROMISE_STATUS_REJECTED;
          this.reason = reason;
          this.rejectedFns.forEach((fn) => {
            fn();
          });
        });
      }
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(fulfilled, rejected) {
    return new MyPromise((resolve, reject) => {
      const defaultOnRejected = (err) => {
        throw err;
      };
      rejected = rejected || defaultOnRejected;

      const defaultOnFulfilled = (value) => {
        return value;
      };
      fulfilled = fulfilled || defaultOnFulfilled;

      if (this.status === PROMISE_STATUS_FULFILLED && fulfilled) {
        execFunctionWithCatchError(fulfilled, this.value, resolve, reject);
      }
      if (this.status === PROMISE_STATUS_REJECTED && rejected) {
        execFunctionWithCatchError(rejected, this.reason, resolve, reject);
      }
      if (this.status === PROMISE_STATUS_PENDING) {
        if (fulfilled)
          this.fulfilledFns.push(() => {
            execFunctionWithCatchError(fulfilled, this.value, resolve, reject);
          });
        if (rejected)
          this.rejectedFns.push(() => {
            execFunctionWithCatchError(rejected, this.reason, resolve, reject);
          });
      }
    });
  }

  catch(rejected) {
    return this.then(undefined, rejected);
  }

  finally(onFinally) {
    this.then(
      () => {
        onFinally();
      },
      () => {
        onFinally();
      }
    );
  }
}

// const promise = new MyPromise((resolve, reject) => {
//   console.log("状态pending");
//   // resolve(1111); // resolved/fulfilled
//   reject(2222);
// });

// // 调用then方法多次调用
// promise
//   .then((res) => {
//     console.log("res:", res);
//   })
//   .catch((err) => {
//     console.log("err:", err);
//   });

const promise = new MyPromise((resolve, reject) => {
  console.log("状态pending");
  resolve(1111); // resolved/fulfilled
  // reject(2222)
});

// 调用then方法多次调用
promise
  .then((res) => {
    console.log("res1:", res);
    return "aaaaa";
  })
  .then((res) => {
    console.log("res2:", res);
  })
  .catch((err) => {
    console.log("err:", err);
  })
  .finally(() => {
    console.log("finally");
  });
